﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Configuration;
using System.IO;
using AutoWizard.Data;
using AutoWizard.Dialog;
using AutoWizard.Meta;
using System.Xml.Serialization;
using System.Xml;
using System.Xml.Xsl;
using DevExpress.XtraGrid.Views.Grid;

namespace AutoWizard
{
    public partial class MainForm : Form    
    {
        public MainForm()
        {
            InitializeComponent();
        }

        /***
         *  Enviroment
         */

        #region CurrentPath
        
        string m_CurrentPath = "";

        public string CurrentPath
        {
            get { return m_CurrentPath; }
            set 
            {
                m_CurrentPath = value;
                txtOutputPath.Text = value;
            }
        }
        #endregion

        #region CurrentMeta

        EntityMeta m_CurrentMeta = new EntityMeta();

        public EntityMeta CurrentMeta
        {
            get { return m_CurrentMeta; }
            set 
            {
                m_CurrentMeta = value;
            }
        }

        #endregion

        /***
         *  MenuClick
         */

        #region 指定元数据目录

        private void menuMetaDir_Click(object sender, EventArgs e)
        {
            dlgFolder.SelectedPath = ConfigurationManager.AppSettings["RootPath"];
           
            DialogResult result = dlgFolder.ShowDialog();
            if (result == DialogResult.OK)
            {
                // 根据获得的目录位置重新建立元数据树
                CurrentPath = dlgFolder.SelectedPath;

                TreeMetaRefresh(CurrentPath + "\\Meta");
            }
        }
        #endregion

        #region 从数据库导入

        private void menuDBExport_Click(object sender, EventArgs e)
        {
            // 弹出数据库导出对话框，将目录路径作为参数传入
            DBExportForm dlg = new DBExportForm(CurrentPath);
            if (dlg.ShowDialog() == DialogResult.OK)
            {
                string path = CurrentPath + "\\Meta";
                if (!Directory.Exists(path)) Directory.CreateDirectory(path);

                foreach (EntityMeta meta in dlg.EntityMetas)
                {
                    string fullName = CurrentPath + "\\Meta\\" + meta.TableName + ".meta";

                    if (File.Exists(fullName))
                        File.Delete(fullName);

                    StreamWriter writer = File.CreateText(fullName);

                    XmlSerializer mySerializer = new XmlSerializer(typeof(EntityMeta));
                    mySerializer.Serialize(writer, meta);
                    writer.Close();
                }

                TreeMetaRefresh(CurrentPath + "\\Meta");
            }
        }
        #endregion

        #region 启动

        private void MainForm_Load(object sender, EventArgs e)
        {
            CurrentPath = ConfigurationManager.AppSettings["RootPath"];
            txtXsltPath.Text = ConfigurationManager.AppSettings["XsltPath"];

            TreeMetaRefresh(CurrentPath + "\\Meta");
        }
        #endregion

        #region 改变选择的树节点之前

        private void treeProject_BeforeSelect(object sender, TreeViewCancelEventArgs e)
        {
            // 保存当前选中节点的内容到文件
            SaveNodeMetaInfo(sender as TreeView);
        }
        #endregion

        #region 选中新的树节点

        private void treeProject_AfterSelect(object sender, TreeViewEventArgs e)
        {
            // 当前选中节点的内容刷新元数据信息维护界面
            TreeView tree = sender as TreeView;
            if (tree.SelectedNode != null && tree.SelectedNode.Tag != null
                && tree.SelectedNode.Tag is EntityMeta)
            {
                CurrentMeta = tree.SelectedNode.Tag as EntityMeta;
            }
            else
            {
                CurrentMeta = new EntityMeta();
            }

            txtMdlUsing.DataBindings.Clear();
            txtMdlNameSpace.DataBindings.Clear();
            txtMdlClassName.DataBindings.Clear();
            txtDalUsing.DataBindings.Clear();
            txtDalNameSpace.DataBindings.Clear();
            txtDalClassName.DataBindings.Clear();
            txtBllUsing.DataBindings.Clear();
            txtBllNameSpace.DataBindings.Clear();
            txtBllClassName.DataBindings.Clear();

            txtMdlUsing.DataBindings.Add("Text", CurrentMeta, "GenConfig.MdlConfig.Using");
            txtMdlNameSpace.DataBindings.Add("Text", CurrentMeta, "GenConfig.MdlConfig.Namespace");
            txtMdlClassName.DataBindings.Add("Text", CurrentMeta, "GenConfig.MdlConfig.ClassName");
            txtDalUsing.DataBindings.Add("Text", CurrentMeta, "GenConfig.DalConfig.Using");
            txtDalNameSpace.DataBindings.Add("Text", CurrentMeta, "GenConfig.DalConfig.Namespace");
            txtDalClassName.DataBindings.Add("Text", CurrentMeta, "GenConfig.DalConfig.ClassName");
            txtBllUsing.DataBindings.Add("Text", CurrentMeta, "GenConfig.BllConfig.Using");
            txtBllNameSpace.DataBindings.Add("Text", CurrentMeta, "GenConfig.BllConfig.Namespace");
            txtBllClassName.DataBindings.Add("Text", CurrentMeta, "GenConfig.BllConfig.ClassName");

            gridControl1.DataSource = CurrentMeta.Propertys;
            gridControl1.ForceInitialize();
        }

        #endregion

        #region 更改输出路径

        private void btnOutputPath_Click(object sender, EventArgs e)
        {
            if (dlgFolder.ShowDialog() == DialogResult.OK)
            {
                txtXsltPath.Text = dlgFolder.SelectedPath;
            }
        }
        #endregion

        #region 产生文件

        private void btnGen_Click(object sender, EventArgs e)
        {
            btnGenEntity_Click(sender, e);
            btnGenUI_Click(sender, e);
            MessageBox.Show("完成!");
        }


        private void btnGenEntity_Click(object sender, EventArgs e)
        {
            if (!IsMetaNode())
                return;

            EntityMeta meta = treeProject.SelectedNode.Tag as EntityMeta;
            string xsltPath = GetXSLTPath();
            string path = GetEntityOutputPath();

            string metaFile = GetFilePath(treeProject.SelectedNode);

            List<string> matchs;

            if (chkGenDAL.Checked)
            {
                string dalFile = string.Format("{0}\\DAL\\{1}.cs", path, meta.GenConfig.DalConfig.ClassName);
                matchs = new List<string>();
                matchs.Add(xsltPath + "\\Entity_DAL.xslt");

                GenerateCode(metaFile, matchs, dalFile, false);
            }
            if (chkGenMDL.Checked)
            {
                string mdlFile = string.Format("{0}\\Model\\{1}.cs", path, meta.GenConfig.MdlConfig.ClassName);
                matchs = new List<string>();
                matchs.Add(xsltPath + "\\Entity_MDL.xslt");

                GenerateCode(metaFile, matchs, mdlFile, false);
            }
            if (chkGenBLL.Checked)
            {
                string bllFile = string.Format("{0}\\BLL\\{1}.cs", path, meta.GenConfig.BllConfig.ClassName);
                matchs = new List<string>();
                matchs.Add(xsltPath + "\\Entity_BLL.xslt");

                GenerateCode(metaFile, matchs, bllFile, false);
            }
            if (chkConst.Checked)
            {
                string constFile = string.Format("{0}\\Const\\{1}_Const.cs", path, meta.GenConfig.MdlConfig.ClassName);
                matchs = new List<string>();
                matchs.Add(xsltPath + "\\Entity_Const.xslt");

                GenerateCode(metaFile, matchs, constFile, false);
            }
        }

        private void btnGenUI_Click(object sender, EventArgs e)
        {
            if (!IsMetaNode())
                return;

            EntityMeta meta = treeProject.SelectedNode.Tag as EntityMeta;
            string xsltPath = GetXSLTPath();
            string path = GetUIOutputPath();

            string metaFile = GetFilePath(treeProject.SelectedNode);

            List<string> matchs;

            if (radioTreeGrid.Checked)
            {
                string csFile = string.Format("{0}\\{1}Management.aspx.cs", path, meta.TableName);
                matchs = new List<string>();
                matchs.Add(xsltPath + "\\TreeGrid_cs.xslt");

                GenerateCode(metaFile, matchs, csFile, false);

                string uiFile = string.Format("{0}\\{1}Management.aspx", path, meta.TableName);
                matchs = new List<string>();
                matchs.Add(xsltPath + "\\TreeGrid_aspx.xslt");

                GenerateCode(metaFile, matchs, uiFile, true);
            }

            if (radioGrid.Checked)
            {
                string csFile = string.Format("{0}\\{1}Management.aspx.cs", path, meta.TableName);
                matchs = new List<string>();
                matchs.Add(xsltPath + "\\Grid_cs.xslt");

                GenerateCode(metaFile, matchs, csFile, false);

                string uiFile = string.Format("{0}\\{1}Management.aspx", path, meta.TableName);
                matchs = new List<string>();
                matchs.Add(xsltPath + "\\Grid_aspx.xslt");

                GenerateCode(metaFile, matchs, uiFile, true);
            }
        }

        #endregion

        #region 关闭程序

        private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            SaveNodeMetaInfo(treeProject);
        }
        #endregion


        /***
         *  Function
         */

        #region TreeMetaRefresh

        private void TreeMetaRefresh(string path)
        {
            treeProject.Nodes.Clear();

            // 以选定目录为根节点建立树的根节点
            TreeNode root = new TreeNode ( path );

            if (!Directory.Exists(path)) Directory.CreateDirectory(path);

            // 获得当前目录下的子目录作为分类节点
            string[] dirs = Directory.GetDirectories(path);

            for (int i = 0; i < dirs.Length; i++)
            {
                int index = dirs[i].LastIndexOf("\\");
                TreeNode dirNode = new TreeNode(dirs[i].Substring(index+1));

                // 获得子目录下的Meta文件建立元数据节点
                string[] files = Directory.GetFiles(dirs[i], "*.meta");

                for (int k = 0; k < files.Length; k++)
                {
                    int n = files[k].LastIndexOf("\\");
                    TreeNode fileNode = new TreeNode(files[k].Substring(n + 1));
                    // 将文件内容读取，作为Tag加入节点
                    StreamReader reader = File.OpenText(files[k]);
                    XmlSerializer mySerializer = new XmlSerializer(typeof(EntityMeta));
                    fileNode.Tag = mySerializer.Deserialize(reader);

                    reader.Close();
                    dirNode.Nodes.Add(fileNode);
                }

                if ( files.Length > 0 )
                    root.Nodes.Add(dirNode);
            }
            // 建立根目录下的元数据节点
            string[] rootfiles = Directory.GetFiles(path, "*.meta");

            for (int k = 0; k < rootfiles.Length; k++)
            {
                int n = rootfiles[k].LastIndexOf("\\");
                TreeNode fileNode = new TreeNode(rootfiles[k].Substring(n + 1));
                // 将文件内容读取，作为Tag加入节点
                StreamReader reader = File.OpenText(rootfiles[k]);
                XmlSerializer mySerializer = new XmlSerializer(typeof(EntityMeta));
                fileNode.Tag = mySerializer.Deserialize(reader);
                reader.Close();

                root.Nodes.Add(fileNode);
            }

            treeProject.Nodes.Add(root);
            root.Expand();
            treeProject.Refresh();
        }

        #endregion

        #region GetFilePath

        private string GetFilePath(TreeNode treeNode)
        {
            return GetParentNodePath(treeNode) + "\\" + treeNode.Text;
        }

        #endregion

        #region GetXSLTPath

        private string GetXSLTPath()
        {
            return txtXsltPath.Text.Trim();
        }

        #endregion

        #region GetParentNodePath

        private string GetParentNodePath(TreeNode treeNode)
        {
            if (treeNode.Parent == null)
                return string.Empty;
            else
            {
                string str = GetParentNodePath(treeNode.Parent);
                if ( string.IsNullOrEmpty ( str ) )
                    return treeNode.Parent.Text;
                else
                    return str + "\\" + treeNode.Parent.Text;
            }
        }

        #endregion

        #region GetEntityOutputPath

        private string GetEntityOutputPath()
        {
            string path = txtOutputPath.Text.Trim()+"\\Output";
            string mdlPath = path + "\\Model";
            string dalPath = path + "\\DAL";
            string bllPath = path + "\\BLL";
            string constPath = path + "\\Const";

            if (!Directory.Exists(path))
                Directory.CreateDirectory(path);

            if (!Directory.Exists(mdlPath))
                Directory.CreateDirectory(mdlPath);
            if (!Directory.Exists(dalPath))
                Directory.CreateDirectory(dalPath);
            if (!Directory.Exists(bllPath))
                Directory.CreateDirectory(bllPath);
            if (!Directory.Exists(constPath))
                Directory.CreateDirectory(constPath);

            return path;
        }

        #endregion

        #region GetUIOutputPath

        private string GetUIOutputPath()
        {
            string path = txtOutputPath.Text.Trim()+"\\Output";
            string uiPath = path + "\\UI";

            if (!Directory.Exists(path))
                Directory.CreateDirectory(path);

            if (!Directory.Exists(uiPath))
                Directory.CreateDirectory(uiPath);

            return uiPath;
        }

        #endregion

        #region IsMetaNode

        private bool IsMetaNode()
        {
            bool bMeta = false ;

            do
            {
                if (treeProject.SelectedNode == null)
                    break;

                if (treeProject.SelectedNode.Tag == null)
                    break;

                if (!(treeProject.SelectedNode.Tag is EntityMeta))
                    break;

                bMeta = true;

            } while (false);

            return bMeta;
        }

        #endregion
        
        #region GenerateCode
        /// <summary>
        /// 产生代码
        /// </summary>
        /// <param name="aXmlMetadata">Xml元数据文件</param>
        /// <param name="aPipes">XSLT过滤管道</param>
        /// <param name="aOutFile">输出文件名，带路径</param>
        private void GenerateCode(string aXmlMetadata, List<string> aPipes, string aOutFile, bool isUI)
        {
            XmlDocument docMetaFile = new XmlDocument();
            docMetaFile.Load(aXmlMetadata);
            string strResult = docMetaFile.InnerXml;

            for (int i = 0; i < aPipes.Count; i++)
            {
                XslCompiledTransform xslt = new XslCompiledTransform();
                xslt.Load(aPipes[i].ToString());

                StringReader streamRead = new StringReader(strResult);
                XmlDocument doc = new XmlDocument();
                doc.Load(streamRead);

                StringWriter streamWrite = new StringWriter();

                xslt.Transform(doc.CreateNavigator(), null, streamWrite);

                strResult = streamWrite.ToString();
            }

            // 将内存中的结果保存到文件中
            FileStream fs = new FileStream(aOutFile, FileMode.Create);
            StreamWriter sw ;
            if ( isUI )
                sw = new StreamWriter(fs, System.Text.Encoding.GetEncoding(65001));
            else
                sw = new StreamWriter(fs, System.Text.Encoding.GetEncoding(936));

            // 替换utf-16为GB2312
            strResult = strResult.Replace("charset=utf-16", "charset=GB2312");
            // 替换&lt;为<,替换&gt;为>
            strResult = strResult.Replace("&lt;", "<");//处理小于号
            strResult = strResult.Replace("&gt;", ">");//处理大于号

            // UI替换
            strResult = strResult.Replace("<?xml version=\"1.0\" encoding=\"gb2312\"?>", "");
            strResult = strResult.Replace("<?xml version=\"1.0\" encoding=\"utf-16\"?>", "");
            strResult = strResult.Replace("<?xml version=\"1.0\" encoding=\"utf-8\"?>", "");
            strResult = strResult.Replace("xmlns:asp=\"http://southchina-logistics.com/nywl/asp\"", "");
            strResult = strResult.Replace("xmlns:dxcp=\"http://southchina-logistics.com/dxcp\"", "");
            strResult = strResult.Replace("xmlns:dxe=\"http://southchina-logistics.com/dxe\"", "");
            strResult = strResult.Replace("xmlns:dxp=\"http://southchina-logistics.com/dxp\"", "");
            strResult = strResult.Replace("xmlns:dxwgv=\"http://southchina-logistics.com/dxwgv\"", "");
            strResult = strResult.Replace("xmlns:dxwtl=\"http://southchina-logistics.com/dxwtl\"", "");
            strResult = strResult.Replace("xmlns:fo=\"http://www.w3.org/1999/XSL/Format\"", "");
            strResult = strResult.Replace("xmlns:uc1=\"http://southchina-logistics.com/uc1\"", "");

            sw.Write(strResult);
            sw.Close();

        }
        #endregion

        #region SaveNodeMetaInfo

        private void SaveNodeMetaInfo(TreeView tree)
        {
            if (tree.SelectedNode != null && tree.SelectedNode.Tag != null
                && tree.SelectedNode.Tag is EntityMeta)
            {
                string fullName = GetFilePath(tree.SelectedNode);
                StreamWriter writer = File.CreateText(fullName);

                XmlSerializer mySerializer = new XmlSerializer(typeof(EntityMeta));
                mySerializer.Serialize(writer, tree.SelectedNode.Tag);
                writer.Close();
            }
        }

        #endregion

        private void btnNewValidator_Click(object sender, EventArgs e)
        {
            GridView gridView = gridControl1.MainView as GridView ;
            PropertyMeta obj = gridView.GetFocusedRow() as PropertyMeta;

            obj.Validators.Add(new ValidatorMeta());

            gridControl1.RefreshDataSource();
        }


    }
}